// Package repository internal/repository/role_repository.go
package repository

import (
	"errors"
	"gorm.io/gorm"
	"gozrd-admin-api/internal/entity/model"
	"strconv"
	"time"
)

var (
	RoleNameExist = errors.New("角色名称已存在")
	RoleKeyExist  = errors.New("角色标识已存在")
)

// IRoleRepository 角色仓库接口
type IRoleRepository interface {
	GetSysRoleByName(roleName string) (model.SysRole, error)
	GetSysRoleByKey(roleKey string) (model.SysRole, error)
	CreateSysRole(role model.SysRole) error
	GetSysRoleById(id int) (model.SysRole, error)
	UpdateSysRole(role model.SysRole) (model.SysRole, error)
	DeleteSysRoleById(id int) error
	UpdateSysRoleStatus(id int, status int) error
	GetSysRoleList(pageNum, pageSize int, roleName, status, beginTime, endTime string) ([]model.SysRole, int64, error)
	QuerySysRoleList() ([]model.SysRole, error)
	QueryRoleMenuIdList(id int) ([]int, error)
	AssignPermissions(roleId int, menuIds []int) error
}

// RoleRepository 角色仓库实现
type RoleRepository struct {
	db *gorm.DB
}

// NewRoleRepository 创建角色仓库
func NewRoleRepository(db *gorm.DB) IRoleRepository {
	return &RoleRepository{
		db: db,
	}
}

// GetSysRoleByName 根据名称查询角色
func (r *RoleRepository) GetSysRoleByName(roleName string) (model.SysRole, error) {
	var role model.SysRole
	err := r.db.Where("role_name = ?", roleName).First(&role).Error
	return role, err
}

// GetSysRoleByKey 根据角色Key查询
func (r *RoleRepository) GetSysRoleByKey(roleKey string) (model.SysRole, error) {
	var role model.SysRole
	err := r.db.Where("role_key = ?", roleKey).First(&role).Error
	return role, err
}

// CreateSysRole 新增角色
func (r *RoleRepository) CreateSysRole(role model.SysRole) error {
	// 检查角色名称是否已存在
	existingRoleByName, err := r.GetSysRoleByName(role.RoleName)
	if err != nil && err != gorm.ErrRecordNotFound {
		return err
	}
	if existingRoleByName.ID > 0 {
		return RoleNameExist
	}

	// 检查角色标识是否已存在
	existingRoleByKey, err := r.GetSysRoleByKey(role.RoleKey)
	if err != nil && err != gorm.ErrRecordNotFound {
		return err
	}
	if existingRoleByKey.ID > 0 {
		return RoleKeyExist
	}

	// 设置创建时间
	role.CreateTime = time.Now()

	// 创建角色
	return r.db.Create(&role).Error
}

// GetSysRoleById 根据id获取角色详情
func (r *RoleRepository) GetSysRoleById(id int) (model.SysRole, error) {
	var role model.SysRole
	err := r.db.First(&role, id).Error
	return role, err
}

// UpdateSysRole 修改角色
func (r *RoleRepository) UpdateSysRole(role model.SysRole) (model.SysRole, error) {
	// 使用事务确保原子性
	tx := r.db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 查询角色是否存在
	var existingRole model.SysRole
	if err := tx.First(&existingRole, role.ID).Error; err != nil {
		tx.Rollback()
		return model.SysRole{}, err
	}

	// 更新字段
	existingRole.RoleName = role.RoleName
	existingRole.RoleKey = role.RoleKey
	existingRole.Status = role.Status
	if role.Description != "" {
		existingRole.Description = role.Description
	}

	// 保存更改
	if err := tx.Save(&existingRole).Error; err != nil {
		tx.Rollback()
		return model.SysRole{}, err
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		tx.Rollback()
		return model.SysRole{}, err
	}

	return existingRole, nil
}

// DeleteSysRoleById 根据id删除角色
func (r *RoleRepository) DeleteSysRoleById(id int) error {
	// 开始事务
	tx := r.db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 删除角色
	if err := tx.Delete(&model.SysRole{}, id).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 删除角色菜单关联
	if err := tx.Where("role_id = ?", id).Delete(&model.SysRoleMenu{}).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 提交事务
	return tx.Commit().Error
}

// UpdateSysRoleStatus 更新角色状态
func (r *RoleRepository) UpdateSysRoleStatus(id int, status int) error {
	return r.db.Model(&model.SysRole{}).Where("id = ?", id).Update("status", status).Error
}

// GetSysRoleList 分页查询角色列表
func (r *RoleRepository) GetSysRoleList1111(pageNum, pageSize int, roleName, status, beginTime, endTime string) ([]model.SysRole, int64, error) {
	var roles []model.SysRole
	var count int64

	db := r.db.Model(&model.SysRole{})

	// 添加查询条件
	if roleName != "" {
		db = db.Where("role_name = ?", roleName)
	}
	if status != "" {
		db = db.Where("status = ?", status)
	}
	if beginTime != "" && endTime != "" {
		db = db.Where("create_time BETWEEN ? AND ?", beginTime, endTime)
	}

	// 获取总数
	err := db.Count(&count).Error
	if err != nil {
		return nil, 0, err
	}

	// 分页查询
	err = db.Limit(pageSize).Offset((pageNum - 1) * pageSize).
		Order("create_time desc").
		Find(&roles).Error

	return roles, count, err
}

// GetSysRoleList 分页查询角色列表
func (r *RoleRepository) GetSysRoleList(pageNum, pageSize int, roleName, status, beginTime, endTime string) ([]model.SysRole, int64, error) {
	var roles []model.SysRole
	var count int64

	db := r.db.Model(&model.SysRole{})

	// 添加查询条件
	if roleName != "" {
		db = db.Where("role_name = ?", roleName)
	}
	if status != "" {
		statusInt, err := strconv.Atoi(status)
		if err == nil {
			db = db.Where("status = ?", statusInt)
		}
	}
	if beginTime != "" && endTime != "" {
		db = db.Where("create_time BETWEEN ? AND ?", beginTime, endTime)
	}

	// 获取总数
	err := db.Count(&count).Error
	if err != nil {
		return nil, 0, err
	}

	// 分页查询
	err = db.Limit(pageSize).Offset((pageNum - 1) * pageSize).
		Order("create_time desc").
		Find(&roles).Error

	return roles, count, err
}

// QuerySysRoleList 获取角色列表(用于下拉选择)
func (r *RoleRepository) QuerySysRoleList() ([]model.SysRole, error) {
	var roles []model.SysRole
	err := r.db.Select("id, role_name").Find(&roles).Error
	return roles, err
}

// QueryRoleMenuIdList 根据角色id查询菜单权限ID列表
func (r *RoleRepository) QueryRoleMenuIdList(id int) ([]int, error) {
	const menuType int = 3
	var ids []int

	err := r.db.Table("sys_menu sm").
		Select("sm.id").
		Joins("LEFT JOIN sys_role_menu srm ON srm.menu_id = sm.id").
		Joins("LEFT JOIN sys_role sr ON sr.id = srm.role_id").
		Where("sm.menu_type = ?", menuType).
		Where("sr.id = ?", id).
		Pluck("sm.id", &ids).Error

	return ids, err
}

// AssignPermissions 分配权限
func (r *RoleRepository) AssignPermissions(roleId int, menuIds []int) error {
	// 开始事务
	tx := r.db.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 删除原有权限
	if err := tx.Where("role_id = ?", roleId).Delete(&model.SysRoleMenu{}).Error; err != nil {
		tx.Rollback()
		return err
	}

	// 添加新权限
	for _, menuId := range menuIds {
		roleMenu := model.SysRoleMenu{
			RoleId: roleId,
			MenuId: menuId,
		}
		if err := tx.Create(&roleMenu).Error; err != nil {
			tx.Rollback()
			return err
		}
	}

	// 提交事务
	return tx.Commit().Error
}
